package com.bestv.bsr.core.service.impl;

import com.bestv.bsr.core.constants.CacheConstants;
import com.bestv.bsr.core.constants.ServiceCodeEnum;
import com.bestv.bsr.core.context.RecommendContext;
import com.bestv.bsr.core.context.RecommendContextHolder;
import com.bestv.bsr.core.entities.params.BsrRequestParams;
import com.bestv.bsr.core.entities.vo.RecDataVo;
import com.bestv.bsr.core.exceptions.ServiceException;
import com.bestv.bsr.core.properties.GlobalProperties;
import com.bestv.bsr.core.service.BsrManageService;
import com.bestv.bsr.core.service.IRecommendEngine;
import com.bestv.bsr.core.service.RecommendEngineFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RSet;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.Set;

/**
 * @author taojiacheng
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class BsrManageServiceImpl implements BsrManageService, InitializingBean {

    private final GlobalProperties globalProperties;

    /**
     * 可用的aiSource
     */
    private final Set<String> enabledAiSourceSet = new HashSet<>();

    private final RedissonClient redissonClient;
    private final RecommendEngineFactory recommendEngineFactory;

    /**
     * todo 配置文件切换能力
     */
    @Override
    public void afterPropertiesSet() {
        enabledAiSourceSet.addAll(globalProperties.getEnabledAiSources());
        RSet<String> rSet = redissonClient.getSet(CacheConstants.ENABLED_AI_SOURCES);
        rSet.addAll(globalProperties.getEnabledAiSources());
    }

    @Scheduled(initialDelay = 10000, fixedDelay = 10000)
    public void refreshEnabledAiSource() {
        RSet<String> rSet = redissonClient.getSet(CacheConstants.ENABLED_AI_SOURCES);
        enabledAiSourceSet.addAll(rSet);
    }


    @Override
    public boolean isAiSourceAvailable(String... aiSources) {
        for (String aiSource : aiSources) {
            if (enabledAiSourceSet.contains(aiSource)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public RecommendContext initRecommendContext(BsrRequestParams requestParams) {
        int size = getSize(requestParams);
        RecommendContext recommendContext = new RecommendContext()
                .setUserId(requestParams.getUserId())
                .setUserAccount(requestParams.getUserAccount())
                .setSceneId(requestParams.getSceneId())
                .setAiSource(requestParams.getAiSource())
                .setMac(requestParams.getMac())
                .setTvProfile(requestParams.getTvProfile())
                .setSize(size)
                .setUserGroup(requestParams.getUserGroup())
                .setApkCode(requestParams.getApkCode());
        String tvId = requestParams.getTvid();
        if (StringUtils.isNotBlank(tvId)) {
            String[] tvIds = requestParams.getTvid().split("\\$");
            recommendContext.setSn(tvIds[tvIds.length - 1]);
        }
        String tvProfile = requestParams.getTvProfile();
        if (StringUtils.isNotBlank(tvProfile)) {
            String[] tvProfiles = requestParams.getTvProfile().split("/");
            recommendContext.setOsProfile(tvProfiles[tvProfiles.length - 1]);
        }
        // 安徽移动参数处理
        recommendContext.setUserGroup(requestParams.getUserGroup())
                .setRuleCode(requestParams.getRuleCode())
                .setPartnerUserAccount(requestParams.getPartnerUserAccount())
                .setDeviceid(requestParams.getDeviceid())
                .setAhCodes(requestParams.getAhCodes());
        return recommendContext;
    }


    protected int getSize(BsrRequestParams requestParams) {
        int size = 0;
        try {
            if (StringUtils.isNotBlank(requestParams.getSize())) {
                size = Integer.parseInt(requestParams.getSize());
            }
        } catch (Exception e) {
            log.error("size is invalid, size: {}", requestParams.getSize());
            throw new ServiceException(ServiceCodeEnum.SIZE_INVALID);
        }
        if (size <= 0) {
            throw new ServiceException(ServiceCodeEnum.SIZE_INVALID);
        }
        if (size > globalProperties.getMaxRecommendSize()) {
            size = globalProperties.getMaxRecommendSize();
        }
        return size;
    }


    @Override
    public RecDataVo doRecommend(RecommendContext recommendContext) {
        if (!isAiSourceAvailable(recommendContext.getAiSource())) {
            throw new ServiceException(ServiceCodeEnum.AI_SOURCE_NOT_AVAILABLE);
        }
        RecDataVo recDataVo;
        try {
            RecommendContextHolder.setRecommendContext(recommendContext);
            IRecommendEngine recommendEngine = recommendEngineFactory.getRecommendEngine(recommendContext.getAiSource());
            recommendEngine.validate(recommendContext);
            recommendEngine.init(recommendContext);
            recDataVo = recommendEngine.recommend(recommendContext);
            return recDataVo;
        } finally {
            RecommendContextHolder.clearRecommendContext();
        }
    }
}
